﻿namespace KeRui.Upload
{
    using System;
    using System.IO;
    using System.Reflection;
    using System.Web;
    using System.Web.Configuration;

    internal class ProgressUtils
    {
        public static StateInfo CreateState(string inID)
        {
            int newID = 0;
            try
            {
                newID = Convert.ToInt32(inID);
            }
            catch
            {
                newID = SharedState.GetNewID();
            }
            return SharedState.Create(newID);
        }

        public static void DoUpload(ProgressModule inModule, HttpApplication inApp, StateInfo inState, Settings inSet, string inDumpPath)
        {
            int num;
            int chunkSize = inSet.Advanced.ChunkSize;
            HttpWorkerRequest workerRequest = GetWorkerRequest(inApp);
            DataStore inData = new DataStore();
            inState.Note = inSet.Notes.GettingSize;
            inModule.DoUpdateProgress(inState.ID);
            int num3 = num = inApp.Request.ContentLength;
            int codePage = inApp.Request.ContentEncoding.CodePage;
            inState.SetState(0, num);
            inModule.DoUpdateProgress(inState.ID);
            inState.Note = inSet.Notes.CheckingSize;
            inModule.DoUpdateProgress(inState.ID);
            int maxRequestLength = GetMaxRequestLength(inApp);
            if (num > maxRequestLength)
            {
                inState.Note = inSet.Notes.UploadTooLarge;
                inModule.DoUpdateProgress(inState.ID);
            }
            else
            {
                byte[] uploadData;
                inData.Init(inSet, codePage);
                inState.Note = inSet.Notes.Preloading;
                inModule.DoUpdateProgress(inState.ID);
                if (num3 > 0)
                {
                    uploadData = workerRequest.GetPreloadedEntityBody();
                    if (uploadData != null)
                    {
                        if (chunkSize <= 10)
                        {
                            chunkSize = uploadData.Length;
                        }
                        num3 -= uploadData.Length;
                        inState.FileName = inData.Add(uploadData);
                        inState.SetState(uploadData.Length, num);
                        inModule.DoUpdateProgress(inState.ID);
                    }
                }
                inState.Note = inSet.Notes.Transferring;
                inModule.DoUpdateProgress(inState.ID);
                while (num3 > 0)
                {
                    if (chunkSize > num3)
                    {
                        chunkSize = num3;
                    }
                    uploadData = new byte[chunkSize];
                    int newSize = workerRequest.ReadEntityBody(uploadData, chunkSize);
                    if (newSize <= 0)
                    {
                        inState.Note = inSet.Notes.UploadStopped;
                        inModule.DoUpdateProgress(inState.ID);
                        inData.Clear();
                        return;
                    }
                    num3 -= newSize;
                    if (newSize < chunkSize)
                    {
                        Array.Resize<byte>(ref uploadData, newSize);
                    }
                    inState.SetState(num - num3, num);
                    inState.FileName = inData.Add(uploadData);
                    inModule.DoUpdateProgress(inState.ID);
                    uploadData = null;
                }
                if (inDumpPath != null)
                {
                    inData.Clear();
                    string inValue = ReadUploadData(inDumpPath, inData, chunkSize);
                    SetContentType(inApp.Request, inValue);
                }
                uploadData = inData.GetUploadData(num);
                SetUploadData(workerRequest, uploadData);
                inData.FinishUp(inApp, inSet);
                inState.Note = inSet.Notes.Finishing;
                inModule.DoUpdateProgress(inState.ID);
            }
        }

        private static int GetMaxRequestLength(HttpApplication inApp)
        {
            int num = 0x800000;
            try
            {
                HttpRuntimeSection section = (HttpRuntimeSection) WebConfigurationManager.OpenWebConfiguration("~").GetSection("system.web/httpRuntime");
                num = section.MaxRequestLength * 0x400;
            }
            catch (Exception exception)
            {
                Log.UniqueError("Unable to get maximum request length.", exception.Message);
            }
            return num;
        }

        private static HttpWorkerRequest GetWorkerRequest(HttpApplication inApp)
        {
            BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
            Type type = inApp.Context.GetType();
            HttpWorkerRequest request = null;
            try
            {
                request = (HttpWorkerRequest) type.GetProperty("WorkerRequest", bindingAttr).GetValue(inApp.Context, null);
            }
            catch (Exception exception)
            {
                Log.UniqueError("Unable to get worker thread.", exception.Message);
            }
            return request;
        }

        public static string ReadUploadData(string inFilePath, DataStore inData, int inChunkSize)
        {
            byte[] buffer;
            FileStream stream = new FileStream(inFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            for (long i = stream.Length; i > 0L; i -= buffer.Length)
            {
                if (i < inChunkSize)
                {
                    buffer = new byte[i];
                }
                else
                {
                    buffer = new byte[inChunkSize];
                }
                stream.Read(buffer, 0, buffer.Length);
                inData.Add(buffer);
            }
            stream.Close();
            return inData.GetBoundary();
        }

        private static void SetContentType(HttpRequest inReq, string inValue)
        {
            BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
            Type type = inReq.GetType();
            try
            {
                type.GetField("_contentType", bindingAttr).SetValue(inReq, inValue);
            }
            catch (Exception exception)
            {
                Log.UniqueError("Unable to set content type.", exception.Message);
            }
        }

        private static byte[] SetUploadData(HttpWorkerRequest inWR, byte[] inData)
        {
            BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
            Type baseType = inWR.GetType();
            int length = inData.Length;
            while (true)
            {
                if (((baseType == null) || (baseType.FullName == "System.Web.Hosting.ISAPIWorkerRequest")) || (baseType.FullName == "Microsoft.VisualStudio.WebHost.Request"))
                {
                    if (baseType == null)
                    {
                        Log.UniqueError("Unable to set upload data.");
                    }
                    if ((baseType != null) && (baseType.FullName == "System.Web.Hosting.ISAPIWorkerRequest"))
                    {
                        try
                        {
                            baseType.GetField("_contentAvailLength", bindingAttr).SetValue(inWR, length);
                            baseType.GetField("_contentTotalLength", bindingAttr).SetValue(inWR, length);
                            baseType.GetField("_preloadedContent", bindingAttr).SetValue(inWR, inData);
                            baseType.GetField("_preloadedContentRead", bindingAttr).SetValue(inWR, true);
                        }
                        catch (Exception exception)
                        {
                            Log.UniqueError("Unable to set upload data properties.", exception.Message);
                        }
                    }
                    if ((baseType != null) && (baseType.FullName == "Microsoft.VisualStudio.WebHost.Request"))
                    {
                        try
                        {
                            baseType.GetField("_contentLength", bindingAttr).SetValue(inWR, length);
                            baseType.GetField("_preloadedContent", bindingAttr).SetValue(inWR, inData);
                            baseType.GetField("_preloadedContentLength", bindingAttr).SetValue(inWR, length);
                        }
                        catch (Exception exception2)
                        {
                            Log.UniqueError("Unable to set debug upload data properties.", exception2.Message);
                        }
                    }
                    return inData;
                }
                baseType = baseType.BaseType;
            }
        }
    }
}

